""" fastapi实例及路由控制 """

from fastapi import Depends, FastAPI, Response, Request
from fastapi.responses import JSONResponse
from starlette import status
from database.database import SessionLocal, engine, Base
from sqlalchemy.orm import Session
import repository.user as userRepository
import repository.category as cateRepository
import repository.article as articleRepository
from schema.user import User, UserCreate, LoginModel, TokenModel
from schema.category import CategoryCreate, CategoryUpdate
from schema.article import ArticleCreate, ArticleUpdate
from starlette.middleware.cors import CORSMiddleware
from util import jwt, pwd
from util.jwt import check_token
from util.markdown import markdown_to_html
from util.my_exceptions import MyBaseException, TokenException

# 数据库初始化，如果没有库或者表，会自动创建
Base.metadata.create_all(bind=engine)

# 创建fastapi实例
app = FastAPI()


# 注册自定义异常: MyBaseException
@app.exception_handler(MyBaseException)
async def my_base_exception_handler(request: Request, exc: MyBaseException):
    return JSONResponse(
        status_code=exc.status_code,
        content={
            "code": exc.code,
            "msg": exc.msg,
            "data": exc.data
        },
    )


# 注册自定义异常: TokenException
@app.exception_handler(TokenException)
async def token_exception_handler(request: Request, exc: TokenException):
    return JSONResponse(
        status_code=401,
        content={
            "code": exc.code,
            "msg": exc.msg,
            "data": None
        },
    )


# 设置跨域
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],  # 设置允许的origins来源
    allow_credentials=True,
    allow_methods=["*"],  # 设置允许跨域的http方法，比如 get、post、put等。
    allow_headers=["*"])  # 允许跨域的headers，可以用来鉴别来源等作用。


# Dependency
async def get_db():
    """
    每一个请求处理完毕后会关闭当前连接，不同的请求使用不同的连接
    """
    try:
        db = SessionLocal()
        yield db
    finally:
        db.close()


# 用户注册
@app.post("/api/register", response_model=User)
async def create_user(user: UserCreate, db: Session = Depends(get_db)):
    # 判断用户是否存在
    db_user = userRepository.get_user_by_username(db, username=user.username)
    if db_user:
        return {"code": 400, "msg": "用户已存在", "data": None}

    return userRepository.create_user(db=db, user=user)


# 用户登录
@app.post("/api/login")
async def login(user_login: LoginModel, response: Response, db: Session = Depends(get_db), response_model=TokenModel):
    # 根据用户名查找
    user = userRepository.get_user_by_username(
        db=db, username=user_login.username)
    if user is None:
        response.status_code = status.HTTP_404_NOT_FOUND
        return {"code": 404, "msg": "用户不存在", "data": None}
    # 验证密码
    if not pwd.verify_password(user_login.password, user.password):
        response.status_code = status.HTTP_401_UNAUTHORIZED
        return {"code": 404, "msg": "密码错误", "data": None}
    # 生成token
    data = {"sub": user.username}
    token = jwt.create_token(data=data)
    return {
        "code": 200,
        "msg": "获取成功",
        "data": {
            "id": user.id,
            "username": user.username
        },
        "token": token
    }


# 获取当前用户
@app.get("/api/currentuser", status_code=status.HTTP_200_OK)
async def get_user(username: str = Depends(check_token)):
    if username:
        user = userRepository.get_user_by_username(username)
        if user:
            return {"code": 200, "msg": "获取成功", "data": user}
        return {"code": 500, "msg": "error", "data": None}


# 获取用户列表
@app.get("/api/users", status_code=status.HTTP_200_OK)
async def get_users(db: Session = Depends(get_db)):
    users = userRepository.get_users(db)
    return {"code": 200, "msg": "获取成功", "data": users}


# 用户详情
@app.get("/api/user/{user_id}", response_model=User, status_code=status.HTTP_200_OK)
async def get_user(user_id: int, response: Response, db: Session = Depends(get_db)):
    db_user = userRepository.get_user(db, user_id=user_id)
    if db_user is None:
        response.status_code = status.HTTP_404_NOT_FOUND
        return {"code": 404, "msg": "用户不存在", "data": None}
    return db_user


# 删除用户
@app.delete("/api/user/{user_id}", status_code=status.HTTP_200_OK)
async def delete_user(user_id: int, response: Response, db: Session = Depends(get_db),
                      username: str = Depends(check_token)):
    if username:
        db_user = userRepository.delete_user(db, user_id=user_id)
        if db_user is None:
            response.status_code = status.HTTP_404_NOT_FOUND
            return {"code": 404, "msg": "用户不存在", "data": None}
        return {"msg": "用户删除成功"}


# # 更新用户信息
# @app.put("/api/user/{user_id}")
# async def update_user(user_id: int, response: Response, update_user: UserUpdate, db: Session = Depends(get_db)):
#     updated_user = userRepository.update_user(db, user_id, update_user)
#     if updated_user is None:
#         return {"code": 404, "msg": "用户不存在", "data": None}
#     return updated_user


# 新增分类
@app.post("/api/category", status_code=status.HTTP_201_CREATED)
async def create_category(cate: CategoryCreate, response: Response, db: Session = Depends(get_db),
                          username: str = Depends(check_token)):
    if username:
        # 判断分类是否存在
        db_category = cateRepository.get_by_name(db, name=cate.name)
        if db_category:
            response.status_code = status.HTTP_400_BAD_REQUEST
            return {"code": 400, "msg": "分类已存在", "data": None}

        cate1 = cateRepository.create_category(db=db, name=cate.name)
        if cate1:
            return {"code": 200, "msg": "新增分类成功", "data": cate1}
        response.status_code = status.HTTP_500_INTERNAL_SERVER_ERROR
        return {"code": 500, "msg": "error", "data": None}


# 更新分类
@app.put("/api/category/{cate_id}", status_code=status.HTTP_200_OK)
async def update_category(cate_id: int, cate: CategoryUpdate, response: Response, db: Session = Depends(get_db),
                          username: str = Depends(check_token)):
    if username:
        # 判断分类是否存在
        db_category = cateRepository.get_by_id(db, cate_id)
        if db_category is None:
            response.status_code = status.HTTP_404_NOT_FOUND
            return {"code": 404, "msg": "分类不存在", "data": None}

        cate1 = cateRepository.update_category(db, cate_id, cate)
        if cate1:
            return {"code": 200, "msg": "分类更新成功", "data": cate1}
        response.status_code = status.HTTP_500_INTERNAL_SERVER_ERROR
        return {"code": 500, "msg": "error", "data": None}


# 分类列表
@app.get("/api/categories", status_code=status.HTTP_200_OK)
async def get_categorys(db: Session = Depends(get_db)):
    cates = cateRepository.get_categories(db)
    return {"code": 200, "msg": "获取成功", "data": cates}


# 分类详情
@app.get("/api/category/{cate_id}", status_code=status.HTTP_200_OK)
async def get_category(cate_id: int, response: Response, db: Session = Depends(get_db)):
    db_category = cateRepository.get_by_id(db, cate_id=cate_id)
    if db_category is None:
        response.status_code = status.HTTP_404_NOT_FOUND
        return {"code": 404, "msg": "分类不存在", "data": None}
    return {"code": 200, "msg": "获取成功", "data": db_category}


# 分类下文章列表
@app.get("/api/category/{cate_id}/artlist", status_code=status.HTTP_200_OK)
async def get_cate_arts(cate_id: int, db: Session = Depends(get_db)):
    arts = cateRepository.get_cate_arts(db, cate_id)
    return {"code": 200, "msg": "获取成功", "data": arts}


# 删除分类
@app.delete("/api/category/{cate_id}", status_code=status.HTTP_200_OK)
async def delete_category(cate_id: int, response: Response, db: Session = Depends(get_db),
                          username: str = Depends(check_token)):
    if username:
        db_category = cateRepository.delete_category(db, cate_id=cate_id)
        if db_category is None:
            response.status_code = status.HTTP_404_NOT_FOUND
            return {"code": 404, "msg": "分类不存在", "data": None}
        return {"code": 200, "msg": "分类删除成功", "data": None}


# 新增文章
@app.post("/api/article", status_code=status.HTTP_201_CREATED)
async def create_article(art: ArticleCreate, response: Response, db: Session = Depends(get_db),
                         username: str = Depends(check_token)):
    if username:
        art1 = articleRepository.create_article(db, art)
        if art1:
            return {"code": 200, "msg": "新增文章成功", "data": art1}
        response.status_code = status.HTTP_500_INTERNAL_SERVER_ERROR
        return {"code": 500, "msg": "error", "data": None}


# 删除文章
@app.delete("/api/article/{art_id}", status_code=status.HTTP_200_OK)
async def delete_article(art_id: int, response: Response, db: Session = Depends(get_db),
                         username: str = Depends(check_token)):
    if username:
        db_article = articleRepository.delete_article(db, art_id)
        if db_article is None:
            response.status_code = status.HTTP_404_NOT_FOUND
            return {"code": 404, "msg": "文章不存在", "data": None}


# 更新文章
@app.put("/api/article/{art_id}", status_code=status.HTTP_200_OK)
async def update_article(art_id: int, article: ArticleUpdate, response: Response, db: Session = Depends(get_db),
                         username: str = Depends(check_token)):
    if username:
        # 判断文章是否存在
        db_article = articleRepository.get_by_id(db, art_id)
        if db_article is None:
            response.status_code = status.HTTP_404_NOT_FOUND
            return {"code": 404, "msg": "文章不存在", "data": None}

        art1 = articleRepository.update_article(db, art_id, article)
        if art1:
            return {"code": 200, "msg": "文章更新成功", "data": art1}
        response.status_code = status.HTTP_500_INTERNAL_SERVER_ERROR
        return {"code": 500, "msg": "error", "data": None}


# 分页获取文章列表
@app.get("/api/articles", status_code=status.HTTP_200_OK)
async def get_articles(page: int = 1, perPage: int = 6, db: Session = Depends(get_db)):
    if page <= 0:
        page = 1
    if perPage <= 0:
        perPage = 6

    arts = articleRepository.get_articles(db, page, perPage)
    count = articleRepository.get_count(db)
    return {"code": 200, "msg": "获取成功", "data": arts, "total": count}


# 获取文章详情
@app.get("/api/article/{article_id}", status_code=status.HTTP_200_OK)
async def get_article_detail(article_id: int, response: Response, db: Session = Depends(get_db)):
    art = articleRepository.get_by_id(db, article_id)
    if art is None:
        response.status_code = status.HTTP_404_NOT_FOUND
        return {"code": 404, "msg": "文章不存在", "data": None}
    # markdown转html
    art.content = markdown_to_html(art.content)
    return {"code": 200, "msg": "获取成功", "data": art}


# 获取文章详情(编辑文章时)
@app.get("/api/article/{article_id}/edit", status_code=status.HTTP_200_OK)
async def get_article_detail(article_id: int, response: Response, db: Session = Depends(get_db)):
    art = articleRepository.get_by_id(db, article_id)
    if art is None:
        response.status_code = status.HTTP_404_NOT_FOUND
        return {"code": 404, "msg": "文章不存在", "data": None}
    return {"code": 200, "msg": "获取成功", "data": art}


# 文章搜索
@app.get("/api/article/search/{search_txt}", status_code=status.HTTP_200_OK)
async def get_article_detail(search_txt: str, db: Session = Depends(get_db)):
    arts = articleRepository.get_by_title(db, search_txt)
    return {"code": 200, "msg": "获取成功", "data": arts}
